package org.jeecg.modules.inspect.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.inspect.entity.InsTask;
import org.jeecg.modules.inspect.entity.InsTaskItem;
import org.jeecg.modules.inspect.mapper.InsTaskItemMapper;
import org.jeecg.modules.inspect.service.IInsTaskItemService;
import org.jeecg.modules.inspect.service.IInsTaskService;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

 /**
 * @Description: 任务
 * @Author: jeecg-boot
 * @Date:   2023-11-24
 * @Version: V1.0
 */
@Api(tags="任务")
@RestController
@RequestMapping("/inspect/insTask")
@Slf4j
public class InsTaskController extends JeecgController<InsTask, IInsTaskService> {

	@Autowired
	private IInsTaskService insTaskService;

	 @Autowired
	 private IInsTaskItemService insTaskItemService;
	 @Resource
	 private InsTaskItemMapper insTaskItemMapper;


	 @Resource
	 private ISysBaseAPI sysBaseApi;


	/*---------------------------------主表处理-begin-------------------------------------*/

	/**
	 * 分页列表查询
	 * @param insTask
	 * @param pageNo
	 * @param pageSize
	 * @param req
	 * @return
	 */
	//@AutoLog(value = "任务-分页列表查询")
	@ApiOperation(value="任务-分页列表查询", notes="任务-分页列表查询")
	@GetMapping(value = "/list")
	public Result<IPage<InsTask>> queryPageList(InsTask insTask,
								   @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
								   @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
								   HttpServletRequest req) {
		QueryWrapper<InsTask> queryWrapper = QueryGenerator.initQueryWrapper(insTask, req.getParameterMap());
		Page<InsTask> page = new Page<InsTask>(pageNo, pageSize);
		IPage<InsTask> pageList = insTaskService.page(page, queryWrapper);
		return Result.OK(pageList);
	}

	 /**
	  * 分页列表查询
	  * @param insTask
	  * @param pageNo
	  * @param pageSize
	  * @param req
	  * @return
	  */
	 //@AutoLog(value = "任务-分页列表查询")
	 @ApiOperation(value="任务-分页列表查询", notes="任务-分页列表查询")
	 @GetMapping(value = "/listReport")
	 public Result<IPage<InsTask>> queryPageListReport(InsTask insTask,
												 @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
												 @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
												 HttpServletRequest req) {
		 QueryWrapper<InsTask> queryWrapper = QueryGenerator.initQueryWrapper(insTask, req.getParameterMap());
		 Page<InsTask> page = new Page<InsTask>(pageNo, pageSize);
		 IPage<InsTask> pageList = insTaskService.page(page, queryWrapper);

		 /**
		  * 2：异常任务周报：
		  * 班次表添加任务类型；任务表添加任务类型及班次外键 任务周月报 任务类型为全天覆盖的
		  * 使用任务班次外建分组判断是否该班次下每个任务项都有打卡记录
		  * 单次全覆盖则判断单挑下全打卡
		  * 使用任务页面
		  * 添加打卡区间查询以及过滤存在漏检的任务 特殊判断全天覆盖时 所有任务最少需要有一条打卡记录 否则算异常漏检
		  */
		 Date startDate = insTask.getStartDate();
		 Date endDate = insTask.getEndDate();
		 List<InsTaskItem> insTaskItemList = insTaskItemService.list();
		 List<InsTask> list = insTaskService.list();
		 List<InsTask> resList = new ArrayList<>();
		 if(CollectionUtils.isNotEmpty(list)){
			 Collections.sort(list, new Comparator<InsTask>() {
				 @Override
				 public int compare(InsTask o1, InsTask o2) {
					 if(o1.getClassId()==null){
						 return 1;
					 }
					 return o1.getClassId().compareTo(o2.getClassId());
				 }
			 });
			 if(startDate!=null){
				 list = list.stream().filter(o->o.getCreateTime().getTime()>=startDate.getTime()).collect(Collectors.toList());
				 if(list==null)  list = new ArrayList<>();
			 }
			 if(endDate!=null){
				 SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd");
				 SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				 String f = format1.format(endDate);
				 Date endTime = endDate;
				 try {
					 endTime = format2.parse((f + " 23:59:59"));
				 }catch (Exception e){}
				 Date finalEndTime = endTime;
				 list = list.stream().filter(o->o.getCreateTime().getTime()<= finalEndTime.getTime()).collect(Collectors.toList());
				 if(list==null)  list = new ArrayList<>();
			 }
			 //根据班次分组
			 Map<String, List<InsTask>> taskGpVal = list.stream().collect(Collectors.groupingBy(o -> StringUtils.isBlank(o.getClassId())?"def":o.getClassId() ));
			 for (String classId : taskGpVal.keySet()) {
				 //取出当前班次全部任务
				 List<InsTask> insTasks = taskGpVal.get(classId);
				 String taskClass = insTasks.get(0).getTaskClass();//任务类型：1单次全覆盖 0全天全覆盖
				 if("0".equals(taskClass)){//0全天全覆盖
					 //按照时间段分组
					 Map<String, List<InsTask>> timeIntervalGpValue = insTasks.stream().collect(Collectors.groupingBy(o -> o.getClassTimePre() + o.getClassTimeEnd()));
					 Set<String> isCheckSet = new HashSet<>();//打卡任务项记录 线路ID+点位ID
					 boolean missDetection = false;//存在某个任务一次都没巡检标识
					 int itemCount = 0;//时间段任务项数
					 for (String interval : timeIntervalGpValue.keySet()) {
						 //取出当前时间段数据
						 List<InsTask> intervalTasks = timeIntervalGpValue.get(interval);
						 List<InsTaskItem> items = new ArrayList<>();
						 //判断区间内是否存在一次打卡记录
						 for (InsTask task : intervalTasks) {
							 if(StringUtils.isBlank(task.getId())){continue;}
							 List<InsTaskItem> itemsSub = insTaskItemList.stream().filter(o->task.getId().equals(o.getTaskId())).collect(Collectors.toList());
//							 List<InsTaskItem> itemsSub = insTaskItemService.selectByMainId(task.getId());
							 if(CollectionUtils.isNotEmpty(itemsSub)) items.addAll(itemsSub);
						 }
						 itemCount = items.size();
						 //过滤出该时间段任务项中已巡检得数据
						 List<InsTaskItem> inspectList = items.stream().filter(o -> "2".equals(o.getItemStatus())).collect(Collectors.toList());
						 if(CollectionUtils.isEmpty(inspectList)){//如果该时间段一个已巡检任务项都没有 视为漏检
							 missDetection=true;
							 intervalTasks.forEach(o->{
								 o.setErrInfo("该时间段内未巡查");
							 });
						 }else{
							 for (InsTaskItem insTaskItem : inspectList) {
								 isCheckSet.add(insTaskItem.getLineId()+insTaskItem.getPointId());
							 }
						 }
					 }
					 //存在漏检
					 if(missDetection ||
							 (itemCount!=isCheckSet.size())){//未打满全部任务项
						 if(!missDetection){
							 insTasks.forEach(o->{
								 o.setErrInfo("未检查完毕");
							 });
						 }
						 resList.addAll(insTasks);
					 }
				 }else{//单次全覆盖
					 for (InsTask task : insTasks) {
						 boolean missDetection = false;
						 if(StringUtils.isBlank(task.getId())){continue;}
//						 List<InsTaskItem> items = insTaskItemService.selectByMainId(task.getId());
						 List<InsTaskItem> items = insTaskItemList.stream().filter(o->task.getId().equals(o.getTaskId())).collect(Collectors.toList());
						 //过滤出任务项中已巡检得数据
						 List<InsTaskItem> inspectList = items.stream().filter(o -> "2".equals(o.getItemStatus())).collect(Collectors.toList());
						 if(items.size()!=inspectList.size()){
							 missDetection=true;task.setErrInfo("未检查完毕");
						 }
						 //存在漏检
						 if(missDetection){
							 resList.add(task);
						 }
					 }

				 }
			 }
		 }
		 pageList.setTotal(resList.size());
		 pageList.setRecords(resList.subList( ((pageNo-1)*pageSize) , (pageNo*pageSize)>resList.size()?resList.size():(pageNo*pageSize) ) );
		 return Result.OK(pageList);
	 }

	 @ApiOperation(value="登录人待办任务-分页列表查询", notes="登录人待办任务-分页列表查询")
	 @GetMapping(value = "/mTask")
	 public Result<List<InsTask>> mTask(InsTask insTask) {
		 LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
		 //String departIds = sysUser.getDepartIds();
		 List<String> departIdList = sysBaseApi.getDepartIdsByUsername(sysUser.getUsername());
		 String departIds = String.join(",",departIdList.stream().map(String::valueOf).collect(Collectors.toList()));

		 List<String> roleIdList = sysBaseApi.getRoleIdsByUsername(sysUser.getUsername());
		 String roleIds = String.join(",",roleIdList.stream().map(String::valueOf).collect(Collectors.toList()));

//		 return Result.OK(insTaskService.todoList(departIds, roleIds ));
		 return Result.OK(insTaskService.todoListByUserName(sysUser.getUsername()));
	 }

	 @ApiOperation(value="登录人待办任务-分页列表查询", notes="登录人待办任务-分页列表查询")
	 @GetMapping(value = "/mAllTask")
	 public Result<List<InsTask>> mAllTask(InsTask insTask) {
		 LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
		 List<String> departIdList = sysBaseApi.getDepartIdsByUsername(sysUser.getUsername());
		 String departIds = String.join(",",departIdList.stream().map(String::valueOf).collect(Collectors.toList()));

		 List<String> roleIdList = sysBaseApi.getRoleIdsByUsername(sysUser.getUsername());
		 String roleIds = String.join(",",roleIdList.stream().map(String::valueOf).collect(Collectors.toList()));

//		 List<InsTask> insTaskList = insTaskService.todoList(departIds, roleIds);
		 List<InsTask> insTaskList = insTaskService.todoListByUserName(sysUser.getUsername());

		for(InsTask task : insTaskList) {
			List<InsTaskItem> insTaskItems = insTaskItemService.selectByMainId(task.getId());
			task.setInsTaskItemList(insTaskItems);
		}

		 return Result.OK(insTaskList);
	 }

	 @ApiOperation(value="登录人待办任务项-列表查询", notes="登录人待办任务项-列表查询")
	 @GetMapping(value = "/mTaskItem")
	 public Result<List<InsTaskItem>> mTaskItem(InsTask insTask) {
		 return Result.ok(insTaskItemService.selectByMainId(insTask.getId()));
	 }

	/**
     *   添加
     * @param insTask
     * @return
     */
    @AutoLog(value = "任务-添加")
    @ApiOperation(value="任务-添加", notes="任务-添加")
    //@RequiresPermissions("org.jeecg.modules:ins_task:add")
    @PostMapping(value = "/add")
    public Result<String> add(@RequestBody InsTask insTask) {
        insTaskService.save(insTask);
        return Result.OK("添加成功！");
    }

    /**
     *  编辑
     * @param insTask
     * @return
     */
    @AutoLog(value = "任务-编辑")
    @ApiOperation(value="任务-编辑", notes="任务-编辑")
    //@RequiresPermissions("org.jeecg.modules:ins_task:edit")
    @RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
    public Result<String> edit(@RequestBody InsTask insTask) {
        insTaskService.updateById(insTask);
        return Result.OK("编辑成功!");
    }

    /**
     * 通过id删除
     * @param id
     * @return
     */
    @AutoLog(value = "任务-通过id删除")
    @ApiOperation(value="任务-通过id删除", notes="任务-通过id删除")
    //@RequiresPermissions("org.jeecg.modules:ins_task:delete")
    @DeleteMapping(value = "/delete")
    public Result<String> delete(@RequestParam(name="id",required=true) String id) {
        insTaskService.delMain(id);
        return Result.OK("删除成功!");
    }

    /**
     * 批量删除
     * @param ids
     * @return
     */
    @AutoLog(value = "任务-批量删除")
    @ApiOperation(value="任务-批量删除", notes="任务-批量删除")
    //@RequiresPermissions("org.jeecg.modules:ins_task:deleteBatch")
    @DeleteMapping(value = "/deleteBatch")
    public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
        this.insTaskService.delBatchMain(Arrays.asList(ids.split(",")));
        return Result.OK("批量删除成功!");
    }

    /**
     * 导出
     * @return
     */
    //@RequiresPermissions("org.jeecg.modules:ins_task:exportXls")
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, InsTask insTask) {
        return super.exportXls(request, insTask, InsTask.class, "任务");
    }

    /**
     * 导入
     * @return
     */
    //@RequiresPermissions("org.jeecg.modules:ins_task:importExcel")
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        return super.importExcel(request, response, InsTask.class);
    }
	/*---------------------------------主表处理-end-------------------------------------*/


    /*--------------------------------子表处理-任务项-begin----------------------------------------------*/
	/**
	 * 通过主表ID查询
	 * @return
	 */
	//@AutoLog(value = "任务项-通过主表ID查询")
	@ApiOperation(value="任务项-通过主表ID查询", notes="任务项-通过主表ID查询")
	@GetMapping(value = "/listInsTaskItemByMainId")
    public Result<IPage<InsTaskItem>> listInsTaskItemByMainId(InsTaskItem insTaskItem,
                                                    @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                    @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                                    HttpServletRequest req) {
        QueryWrapper<InsTaskItem> queryWrapper = QueryGenerator.initQueryWrapper(insTaskItem, req.getParameterMap());
        Page<InsTaskItem> page = new Page<InsTaskItem>(pageNo, pageSize);
        IPage<InsTaskItem> pageList = insTaskItemService.page(page, queryWrapper);
		List<InsTaskItem> records = pageList.getRecords();
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		List<InsTask> taskList = insTaskService.list();
		try{
			for (InsTaskItem record : records) {
				//获取任务判断打卡时间是否在区间内
				List<InsTask> tasks = taskList.stream().filter(o -> o.getId().equals(record.getTaskId())).collect(Collectors.toList());
				InsTask insTask = new InsTask();
				if(CollectionUtils.isNotEmpty(tasks)){
					insTask = tasks.get(0);
				}
				Date taskBegin = insTask.getTaskBegin();//任务开始时间
				Date taskEnd = insTask.getTaskEnd();//任务结束时间

				String classTimePre = record.getClassTimePre();//任务项打卡区间开始时间
				String classTimeEnd = record.getClassTimeEnd();//任务项打卡区间结束时间

				Date insTime = record.getInsTime();//实际打卡时间

				if(insTime==null) continue;
				String insTimeStr = format.format(insTime);//实际打卡时间
				//判断实际打卡时间是否在区间任务规定期间内
				if(taskBegin.before(insTime) && taskEnd.after(insTime)){
					String checkTime = insTimeStr.split(" ")[1];//打卡时间 不带日期
					long classTimePrel  = Long.parseLong(classTimePre.replaceAll(":", ""));//打卡规定开始时间 不带日期
					long classTimeEndl  = Long.parseLong(classTimeEnd.replaceAll(":", ""));//打卡规定结束时间 不带日期
					long checkTimel  = Long.parseLong(checkTime.replaceAll(":", ""));//打卡时间 不带日期
					//在区间内
					if( classTimePrel<=checkTimel && checkTimel<=classTimeEndl ){
						record.setInsTimeColor("green");
					}else{
						record.setInsTimeColor("red");
					}
				}else{
					record.setInsTimeColor("red");
				}


			}
		}catch (Exception e){
			e.printStackTrace();
		}

		return Result.OK(pageList);
    }

	/**
	 * 添加
	 * @param insTaskItem
	 * @return
	 */
	@AutoLog(value = "任务项-添加")
	@ApiOperation(value="任务项-添加", notes="任务项-添加")
	@PostMapping(value = "/addInsTaskItem")
	public Result<String> addInsTaskItem(@RequestBody InsTaskItem insTaskItem) {
		insTaskItemService.save(insTaskItem);
		insTaskItemService.updateStatus(insTaskItem.getTaskId());
		return Result.OK("添加成功！");
	}

    /**
	 * 编辑
	 * @param insTaskItem
	 * @return
	 */
	@AutoLog(value = "任务项-编辑")
	@ApiOperation(value="任务项-编辑", notes="任务项-编辑")
	@RequestMapping(value = "/editInsTaskItem", method = {RequestMethod.PUT,RequestMethod.POST})
	public Result<String> editInsTaskItem(@RequestBody InsTaskItem insTaskItem) {
		insTaskItemService.updateById(insTaskItem);
        insTaskItemService.updateStatus(insTaskItem.getTaskId());
        return Result.OK("编辑成功!");
	}

	/**
	 * 通过id删除
	 * @param id
	 * @return
	 */
	@AutoLog(value = "任务项-通过id删除")
	@ApiOperation(value="任务项-通过id删除", notes="任务项-通过id删除")
	@DeleteMapping(value = "/deleteInsTaskItem")
	public Result<String> deleteInsTaskItem(@RequestParam(name="id",required=true) String id) {
		List<InsTaskItem> insTaskItems = insTaskItemMapper.selectList(Wrappers.<InsTaskItem>lambdaQuery()
				.eq(InsTaskItem::getId, id)
		);
		InsTaskItem insTaskItem = new InsTaskItem();
		if(CollectionUtils.isNotEmpty(insTaskItems)){
			insTaskItem = insTaskItems.get(0);
		}
		insTaskItemService.removeById(id);
		insTaskItemService.updateStatus(insTaskItem.getTaskId());
		return Result.OK("删除成功!");
	}

	/**
	 * 批量删除
	 * @param ids
	 * @return
	 */
	@AutoLog(value = "任务项-批量删除")
	@ApiOperation(value="任务项-批量删除", notes="任务项-批量删除")
	@DeleteMapping(value = "/deleteBatchInsTaskItem")
	public Result<String> deleteBatchInsTaskItem(@RequestParam(name="ids",required=true) String ids) {
	    this.insTaskItemService.removeByIds(Arrays.asList(ids.split(",")));
		return Result.OK("批量删除成功!");
	}

    /**
     * 导出
     * @return
     */
    @RequestMapping(value = "/exportInsTaskItem")
    public ModelAndView exportInsTaskItem(HttpServletRequest request, InsTaskItem insTaskItem) {
		 // Step.1 组装查询条件
		 QueryWrapper<InsTaskItem> queryWrapper = QueryGenerator.initQueryWrapper(insTaskItem, request.getParameterMap());
		 LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

		 // Step.2 获取导出数据
		 List<InsTaskItem> pageList = insTaskItemService.list(queryWrapper);
		 List<InsTaskItem> exportList = null;

		 // 过滤选中数据
		 String selections = request.getParameter("selections");
		 if (oConvertUtils.isNotEmpty(selections)) {
			 List<String> selectionList = Arrays.asList(selections.split(","));
			 exportList = pageList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList());
		 } else {
			 exportList = pageList;
		 }

		 // Step.3 AutoPoi 导出Excel
		 ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
		 //此处设置的filename无效,前端会重更新设置一下
		 mv.addObject(NormalExcelConstants.FILE_NAME, "任务项");
		 mv.addObject(NormalExcelConstants.CLASS, InsTaskItem.class);
		 mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("任务项报表", "导出人:" + sysUser.getRealname(), "任务项"));
		 mv.addObject(NormalExcelConstants.DATA_LIST, exportList);
		 return mv;
    }

    /**
     * 导入
     * @return
     */
    @RequestMapping(value = "/importInsTaskItem/{mainId}")
    public Result<?> importInsTaskItem(HttpServletRequest request, HttpServletResponse response, @PathVariable("mainId") String mainId) {
		 MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		 Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
		 for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
       // 获取上传文件对象
			 MultipartFile file = entity.getValue();
			 ImportParams params = new ImportParams();
			 params.setTitleRows(2);
			 params.setHeadRows(1);
			 params.setNeedSave(true);
			 try {
				 List<InsTaskItem> list = ExcelImportUtil.importExcel(file.getInputStream(), InsTaskItem.class, params);
				 for (InsTaskItem temp : list) {
                    temp.setTaskId(mainId);
				 }
				 long start = System.currentTimeMillis();
				 insTaskItemService.saveBatch(list);
				 log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒");
				 return Result.OK("文件导入成功！数据行数：" + list.size());
			 } catch (Exception e) {
				 log.error(e.getMessage(), e);
				 return Result.error("文件导入失败:" + e.getMessage());
			 } finally {
				 try {
					 file.getInputStream().close();
				 } catch (IOException e) {
					 e.printStackTrace();
				 }
			 }
		 }
		 return Result.error("文件导入失败！");
    }

    /*--------------------------------子表处理-任务项-end----------------------------------------------*/


}
